package log

import (
	"app/config"
	"context"
	"sync"

	"go.uber.org/zap"
)

var (
	instances = make(map[string]*xLogger)
	mu        sync.Mutex
)

func Logger(name ...string) *xLogger {
	var group string
	if len(name) == 0 {
		group = "app"
	} else {
		group = name[0]
	}
	instance, err := GetInstance(group)
	if err != nil {
		panic(err)
	}
	return instance
}

// GetInstance 获取redis 单例
func GetInstance(name string) (instance *xLogger, err error) {
	mu.Lock()
	defer mu.Unlock()
	var ok bool
	if instance, ok = instances[name]; ok {
		return instance, nil
	}
	instance = &xLogger{logger: NewZapLogger(config.Config.Logger).Sugar()}
	instances[name] = instance
	return instance, nil
}

type xLogger struct {
	logger *zap.SugaredLogger
}

func (l *xLogger) Logger() *zap.SugaredLogger {
	return l.logger
}

// 从上下文中获取请求id
func (l *xLogger) WithContext(ctx context.Context) *zap.SugaredLogger {
	return l.logger.With(zap.String("request_id", ctx.Value("request_id").(string)))
}

// Critical implements ILogger.
func (l *xLogger) Critical(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Error(v...)
}

// Criticalf implements ILogger.
func (l *xLogger) Criticalf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Errorf(format, v...)
}

// Debug implements ILogger.
func (l *xLogger) Debug(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Debug(v...)
}

// Debugf implements ILogger.
func (l *xLogger) Debugf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Debugf(format, v...)
}

// Error implements ILogger.
func (l *xLogger) Error(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Error(v...)
}

// Errorf implements ILogger.
func (l *xLogger) Errorf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Errorf(format, v...)
}

// Fatal implements ILogger.
func (l *xLogger) Fatal(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Fatal(v...)
}

// Fatalf implements ILogger.
func (l *xLogger) Fatalf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Fatalf(format, v...)
}

// Info implements ILogger.
func (l *xLogger) Info(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Info(v...)
}

// Infof implements ILogger.
func (l *xLogger) Infof(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Infof(format, v...)
}

// Notice implements ILogger.
func (l *xLogger) Notice(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Info(v...)
}

// Noticef implements ILogger.
func (l *xLogger) Noticef(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Infof(format, v...)
}

// Panic implements ILogger.
func (l *xLogger) Panic(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Panic(v...)
}

// Panicf implements ILogger.
func (l *xLogger) Panicf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Panicf(format, v...)
}

// Warning implements ILogger.
func (l *xLogger) Warning(ctx context.Context, v ...interface{}) {
	l.WithContext(ctx).Warn(v...)
}

// Warningf implements ILogger.
func (l *xLogger) Warningf(ctx context.Context, format string, v ...interface{}) {
	l.WithContext(ctx).Warnf(format, v...)
}
